/* 
 *  @module Mole
 *  Author: Alex Hu
 *
 *  Example:
 *
 *
 */


'use strict';

(function($){

GML.Mole = (function(){
    
    var M = {};

    // M.story = {};

    M.wild = [];

    M.init = function(){
        var that = M
            , doc = document
            ;

        that.room = {};
        that.roomNO = 1;

        that.hoverTO = '';

        $(doc).on('click', '[role|=mole]', function(e){
            var $this = $(this)
                , attr = $this.attr('role').split(' ')
                , i, fresh, type, _top, item, $panel, callback, on, off
                ;

            for(i=0; i<attr.length; i++){
                item = attr[i];
                if(item.indexOf('mole') === 0){
                    switch(item){
                        case 'mole':
                            // type = 'select';
                            that.fire({
                                'el': $this
                            });
                            break;
                        case 'mole-t':
                            // _top = true;
                            that.fire({
                                'el': $this,
                                'top': true
                            });
                            break;
                        case 'mole-s':
                            // type = 'select';
                            that.fire({
                                'el': $this,
                                'type': 'select'
                            });
                            break;
                        case 'mole-f':
                            // fresh = true;
                            that.fire({
                                'el': $this,
                                'fresh': true
                            });
                            break;
                        case 'mole-p':
                            that.panel({
                                'el': $this,
                                'fresh': true
                            });
                            break;
                        case 'mole-p-fx':
                            that.panel({
                                'el': $this,
                                'fixed': true,
                                'fresh': true
                            });
                            break;
                        case 'mole-p-f':
                            that.panel({
                                'el': $this,
                                'fresh': true
                            });
                            break;
                        /*
                        case 'mole-h':
                            that.panel({
                                'el': $this,
                                'type': 'hover'
                            });
                            break;
                            */
                        case 'mole-slide':
                            that.slide($this);
                            /*
                            {
                                'el': $this
                            });
                            */
                            break;
                        case 'mole-mask':
                        case 'mole-close':
                        case 'mole-ok':
                            $panel = that.mask.data('panel');
                            callback = $panel.data('callback');
                            $panel.hide();
                            that.mask.hide();
                            if(callback){
                                if(item.indexOf('ok') > -1){
                                    on = callback.on;
                                    if(on){
                                        on($this, $panel);
                                    }
                                }else{
                                    off = callback.off;
                                    if(off){
                                        off($this, $panel);
                                    }
                                }
                            }
                            break;
                    }
                    break;
                }
            }
            e.preventDefault();
            e.stopImmediatePropagation();
        });

        /* Click the other place take the mole back */
        $(doc).on('click', '*', function(e){
            var $this = $(this);
            if(!$(e.target).closest('.dropDownMenu').length && !$(e.target).closest('.panelMD').length){
                 if(!$this.closest('[role|=mole]').length){
                    var that = M
                        , wild = that.wild
                        , i, item
                        ;

                    if(wild.length){
                        that.shut();
                        /*
                        for(i=0; i<wild.length; i++){
                            item = wild[i];
                            item.hide();
                            item.data('hidden', true);
                        }
                        M.wild = [];
                        */
                    }
                }
            }
        });

        $(doc).on('click', '[role~=ok-mole]', function(e){
            var $this = $(this)
                , $panel = $this.closest('[role=panelMD]')
                , callback = $panel.data('callback')
                ;

            if(callback){
                callback.on();
            }
        });

        // that.hover();

    }

    M.fire = function(c){
        var $this = c.el
            , $mole = $this.data('mole')
            , that = M
            , $input, template, sheep, name, arrow
            ;

        var show = function(r){
            var tH, mH, mW, pos, mLeft, mTop, tW, t, room, marginLeft;

            if(c.fresh || r){
                t = $this.data('t');
                if(!t && !c.bottom){
                    room = GML.Room[$this.data('room')];
                    room['el'] = $this;
                    t = room.t;
                }else{
                    room = $this;
                }
                if(c.bottom){
                    t = 'tip-bottom';
                }
                template = GML.Template.tube[t](room);
                if(c.type === 'hover' && (c.top || c.right || c.bottom)){
                    $mole.find('.box-in').html(template);
                }else{
                    $mole.html(template);
                }
                pos = $this.position();

                $mole.css({
                    'left': -999
                });
                mW = $mole.outerWidth();
                tW = $this.outerWidth();
                marginLeft = parseInt($this.css('marginLeft'));
                if(!marginLeft){
                    marginLeft = 0;
                }
                if(c.top){
                    mH = $mole.outerHeight(true);
                    if(c.type === 'hover'){
                        /*
                        marginLeft = parseInt($this.css('marginLeft'));
                        if(!marginLeft){
                            marginLeft = 0;
                        }
                        */
                        mLeft = pos.left + marginLeft + (mW - tW) / -2;
                        mTop = pos.top + (-1 * mH) - 10;
                        $mole.width(mW);
                    }else{
                        mLeft = pos.left;
                        mTop = pos.top + (-1 * mH);
                    }
                }else{
                    tH = $this.outerHeight(true);
                    if(c.right){
                        mLeft = pos.left + tW - mW;
                        mTop = pos.top + tH + 7;
                    }else if(c.bottom){
                        mLeft = pos.left + marginLeft - (mW - tW) / 2;
                        mTop = pos.top + tH + 8;
                    }else{
                        mLeft = pos.left;
                        mTop = pos.top + tH;
                        if(tW > mW){
                            $mole.width(tW);
                        }else{
                            $mole.width(mW);
                        }
                    }
                }

                $mole.css({
                    'left': mLeft,
                    'top': mTop
                });
            }
            that.wild.push($mole);
            $mole.show();
        }

        that.shut();
        if($mole){
            if($mole.is(':hidden')){
                show();
            /*
            }else{
                that.shut();
                */
            }
        }else{
            // template = GML.Template.tube[$this.data('t')]($this);
            if(c.type === 'hover' && (c.right || c.top || c.bottom)){
                if(c.right || c.bottom){
                    arrow = 't';
                }else{
                    arrow = 'b';
                }
                sheep = [
                    '<div class="tips-default">',
                        '<div class="box-in clear">',
                        '</div>',
                        '<span class="bg-icon arrow-' + arrow + '"></span>',
                    '</div>'
                ];
                $mole = $(sheep.join(''));
                // $mole.find('.box-in').html(template);
            }else{
                $mole = $('<div />', {
                    'class': 'dropDownMenu'
                    // 'html': template
                });
            }
            $mole.insertAfter($this);
            show('init');
            $this.data('mole', $mole);
            $mole.data('trigger', $this);

            if(c.type === 'select'){
                name = $this.data('name');
                $input = $this.parent().find('[name=' + name + ']');
                if(!$input.length){
                    $input = $('<input />', {
                        'type': 'hidden',
                        'name': name
                    });
                    $input.insertAfter($this);
                }
                $mole.data('field', $input);
            }
        }
    }

    M.panel = function(c){
        var $mole, story, roomNO, room, pPos, $cont, template
            , $this = c.el
            , that = M
            , $mask = that.mask
            ;

        if(!$this){
            $this = $("<div />", { "data-t": c.template });
        }else{
            $mole = $this.data('panel');
        }
        template = $this.data('t') || GML.Room[$this.data('room')].t;

        var show = function(r){
            var offset, pos, sizeMole, pLeft, pTop, vp, $content
                , $win = $(window)
                ;

            var centerPanel = function(){
                sizeMole = {
                    'w': $mole.outerWidth(),
                    'h': $mole.outerHeight()
                };
                vp = {
                    'w': $win.width(),
                    'h': $win.height()
                };

                pLeft = (vp.w - sizeMole.w) / 2;
                pTop = (vp.h - sizeMole.h) / 2;

                if(pLeft < 0){
                    pLeft = 0;
                }
                if(pTop < 0){
                    pTop = 0;
                }
                $mole.css({
                    'left': pLeft,
                    'top': pTop + $(document).scrollTop()
                });
            }
                        
            if(c.fresh || r){
                $cont = $mole.children('[role=cont-panel]');
                $cont.html('<div class="spinnerCenter" style="position:static; width:160px; height:60px;"></div>');
                centerPanel();

                GML.When( function(){ return GML.Template.tube[template]($this); }, function(d){
                    $cont.html(d);
                    roomNO = $this.data('room');
                    if(roomNO){
                        room = GML.Room[roomNO];
                        if(room.callback){
                            room.callback($this, $mole);
                        }
                    }
                    centerPanel();
                });
            }

            if(!$mask){
                $mask = $('<div />', {
                    'class': 'shade-div hide',
                    'role': 'mole-mask'
                });
                $mask.appendTo($('body'));
                that.mask = $mask;
            }
            $mask.show();
            $mask.data('panel', $mole);
            $mask.data('shut', function(){
                $mask.data('panel').hide();
                $mask.hide();
            });
            $mole.data('callback', c.callback);
            $mole.show();
        }

        if($mole){
            show();
        }else{
            if(c.fixed){
                pPos = 'win-fixed';
            }else{
                pPos = 'win-absolute';
            }
            story = [
                '<div class="win-pop ' + pPos + '" role="panelMD">',
					'<div class="win-inner" role="cont-panel"></div>',
                    '<a href="javascript:void(0);" class="bg-icon ico-close-btn" role="mole-close"></a>',
                '</div>'
            ];
            $mole = $(story.join(''));
            $mole.appendTo($('body'));
            $this.data('panel', $mole);
            that.collect($this, $mole); 
            show('init');
        }
    }

    M.hover = function(s){
        var $stage = s ? s : $('body')
            , sheep = $stage.find('[role~=mole-h]')
            , that = M
            , i, $item, $mole
            ;

        var addHandler = function(c){ // t, htop, fresh, ){
            var TO;
            c.el.hover(
                function(){
                    clearTimeout(TO);
                    var $this = $(this), on, callback;
                    that.fire({
                        'el': $this,
                        'type': 'hover',
                        'top': c.top,
                        'right': c.right,
                        'bottom': c.bottom,
                        'fresh': c.fresh
                    });
                    callback = $this.data('callback');
                    if(callback){
                        on = callback.on;
                        if(on){
                            on();
                        }
                    }
                    $mole = $this.data('mole');
                    $mole.hover(
                        function(){
                            clearTimeout(TO);
                        },
                        function(){
                            var callback = $this.data('callback'), off;
                            if(callback){
                                off = callback.off;
                                if(off){
                                    off();
                                }
                            }
                            $mole.hide();
                            // that.shut();
                        }
                    );
                },
                function(){
                    var $this = $(this);
                    TO = setTimeout(function(){
                        var callback = $this.data('callback')
                            , $mole = $this.data('mole')
                            , off
                            ;

                        if(callback){
                            off = callback.off;
                            if(off){
                                off();
                            }
                        }
                        $mole.hide();
                        // that.shut();
                    }, 100);
                }
            );
        }

        for(i=0; i<sheep.length; i++){
            addHandler({
                'el': $(sheep[i])
            });
        }

        sheep = $stage.find('[role~=mole-h-t]');
        for(i=0; i<sheep.length; i++){
            addHandler({
                'el': $(sheep[i]),
                'top': true
            });
        }

        sheep = $stage.find('[role~=mole-h-r]');
        for(i=0; i<sheep.length; i++){
            addHandler({
                'el': $(sheep[i]),
                'right': true
            });
        }

        sheep = $stage.find('[role~=mole-h-b]');
        for(i=0; i<sheep.length; i++){
            addHandler({
                'el': $(sheep[i]),
                'bottom': true
            });
        }

        sheep = $stage.find('[role~=mole-h-tf]');
        for(i=0; i<sheep.length; i++){
            addHandler({
                'el': $(sheep[i]),
                'top': true,
                'fresh': true
            });
        }
    }

    M.slide = function(el){
        var $this = el
            , $M = $this.closest('[role=moleMD]')
            , $stage = $this.data('story')
            , $panel, $_stage, type, that
            , roomNO = $this.data('room')
            , that = M
            ;

        if(!$stage){
            $stage = $M.children('.bd')
            $stage.html(GML.Template.tube[$this.data('t')]($this));
            $this.data('story', $stage);
        }
        if($stage.is(':hidden')){ // $this.hasClass('tit-retracting')){
            $this.addClass('tit-unfold');
            $this.removeClass('tit-retracting');
            type = 'unfold';
        }else{
            $this.addClass('tit-retracting');
            $this.removeClass('tit-unfold');
            type = 'fold';
        }
        $panel = $this.closest('.panelMD');
        if($panel.length){
            that = M;
            that.panelCenter({
                'volume': $stage.outerHeight(true),
                'type': type,
                'el': $stage
            });
        }else{
            $stage.slideToggle();
        }
        if(roomNO){
            var room = GML.Room[roomNO];
            if(room.callback){
                room.callback($this, $stage);
            }
        }
    }

    M.panelCenter = function(c){
        var that = M
            , $mask = that.mask
            , $mole, $_mole, volume, config, pVolume, type, viewportH, moleH, range, operate, _moleH, scrollTop
            ;

        if($mask){
            $mole = $mask.data('panel');
            volume = c.volume;
            pVolume = volume / 2;
            type = c.type;
            operate = '+';

            viewportH = $(window).height();
            moleH = $mole.outerHeight(true);

            switch(type){
                case 'fold':
                    _moleH = moleH - volume;
                    break;
                case 'unfold':
                    _moleH = moleH + volume;
                    break;
                default:
                    break;
            }

            scrollTop = document.body.scrollTop;
            if(viewportH < _moleH){
                pVolume = scrollTop;
            }else{
                pVolume = (viewportH - _moleH) / 2;
                if(volume < scrollTop){
                    pVolume = pVolume + scrollTop;
                }
            }
            
            if(_moleH < viewportH || moleH < viewportH){
                $mole.animate({
                    'top': pVolume
                }, 400);
            }
            c.el.slideToggle(400);
        }
    }

    M.shut = function(){
        var that = M
            , wild = that.wild
            , i
            ;

        for(i=0; i<wild.length; i++){
            wild[i].hide();
        }
        that.wild = [];
    }

    M.collect = function(trigger, el){
        var RT = GML.RT
            ;

        if(trigger.closest(RT).length){
            if(RT.data('collect')){
                RT.data('collect').push(el);
            }else{
                RT.data('collect', [ el ]);
            }
        }
    }

    M.init();
    return M;

})();

})(jQuery)

